#include "gd32f10x_gpio.h"
#include "gd32f10x_libopt.h"
#include "options.h"
#include "at5820.h"
static void bsp_io_init(void) {
  /* UART0 GPIO:
   *  TX: PA2
   *  RX: PA3
   */
    rcu_periph_clock_enable(RCU_GPIOA);
    gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_2);
    gpio_init(GPIOA, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_3);
}
static void bsp_usart_init(void) {
    rcu_periph_clock_enable(RCU_USART1);

    usart_deinit(USART1);
    usart_baudrate_set(USART1, 115200);
    usart_word_length_set(USART1, USART_WL_8BIT);
    usart_stop_bit_set(USART1, USART_STB_1BIT);
    usart_parity_config(USART1, USART_PM_NONE);
    usart_hardware_flow_rts_config(USART1, USART_RTS_DISABLE);
    usart_hardware_flow_cts_config(USART1, USART_CTS_DISABLE);
    usart_receive_config(USART1, USART_RECEIVE_ENABLE);
    usart_transmit_config(USART1, USART_TRANSMIT_ENABLE);
    usart_interrupt_enable(USART1, USART_INT_RBNE);
    usart_interrupt_flag_clear(USART1, USART_INT_FLAG_RBNE);
    usart_enable(USART1);
}
static void bsp_nvic_init(void) {
    NVIC_ClearPendingIRQ(USART1_IRQn);
    NVIC_SetPriority(USART1_IRQn, NVIC_PRIORITY_MAKE(4));
    NVIC_EnableIRQ(USART1_IRQn);
}

static uint16_t bsp_write(uint8_t* pbuf, uint16_t length) {
    for (uint16_t i = 0; i < length; ++i) {
        usart_flag_clear(USART1, USART_FLAG_TC);
        usart_data_transmit(USART1, pbuf[i]);
        while (SET != usart_flag_get(USART1, USART_FLAG_TC))
            ;
    }
    return length;
}

/********************************************************************************/
uint8_t FiFo_W = 0;
uint8_t FiFo_R = 0;

uint8_t sensor_get_dis = 0;
typedef struct
{
    uint8_t  Addr_Reading;
    uint8_t  funcode;
    uint8_t  Len;
    uint8_t  Data[HCI_SEND_LEN];
}HCI_FIFO;

HCI_FIFO Hci_FiFo[HCI_FIFO_SIZE];

uint16_t Crc16CheckSum(unsigned char* buf, unsigned char length)
{
    uint16_t Crc16 = 0;
    while (length--)
    {
        Crc16 = Crc16 + *(buf);
        buf++;
    }
    return Crc16;
}
void Protocol_Hci_SendData(uint8_t fifo_R)
{
    if (Hci_FiFo[fifo_R].Len > 0)
    {
        bsp_write(Hci_FiFo[fifo_R].Data, Hci_FiFo[fifo_R].Len);
    }
}
void Protocol_Hci_FiFo_Poll(void)
{
    if (FiFo_R != FiFo_W)
    {
        Protocol_Hci_SendData(FiFo_R);
        if (++FiFo_R >= HCI_FIFO_SIZE)
            FiFo_R = 0;
    }
}

void Protocol_Hci_AddFiFo(void)
{
    if (++FiFo_W >= HCI_FIFO_SIZE)
        FiFo_W = 0;
}

void AT5820_Cmd_Set(uint8_t cmd, uint8_t len, uint8_t data)
{
    uint8_t temp[HCI_SEND_LEN] = { 0 };
    uint8_t i = 0;
    uint16_t crc16;
    temp[i++] = HCI_FRAME_HEAD;
    temp[i++] = cmd;
    temp[i++] = len;
    if (len == 1) {
        temp[i++] = data;
    }
    crc16 = Crc16CheckSum(temp, i);
    temp[i++] = crc16;    //sum_L
    temp[i++] = crc16 >> 8; //sum_H
    memcpy(Hci_FiFo[FiFo_W].Data, temp, i);
    Hci_FiFo[FiFo_W].Len = i;
    Hci_FiFo[FiFo_W].funcode = cmd;
    Protocol_Hci_AddFiFo();
}


void AT5820_Distance_Set(uint8_t grade)//
{
    AT5820_Cmd_Set(HCI_DIST_SET, 1, grade);
    AT5820_Cmd_Set(HCI_CFG_SAVE_SET, 1, 1);//val 1:save  0:no save 
}

void AT5820_Distance_Get(void)
{
    AT5820_Cmd_Set(HCI_DIST_GET, 0, 0);
}

uint8_t Protocol_Hci_RecData(uint8_t* pData, uint8_t DatLen)
{
    uint16_t crc16 = 0;
    uint8_t  cmd = 0;
    uint8_t  ret = false; //
    if (DatLen < 2) return false;
    crc16 = pData[DatLen - 2] + (pData[DatLen - 1] << 8);
    if (crc16 == Crc16CheckSum(pData, DatLen - 2)) {
        cmd = pData[1];
        ret = pData[5];
        if (cmd == HCI_DIST_GET) {
            sensor_get_dis = pData[3];
        }
        return true;
    }
    return false;
}
uint8_t Rx_Buf[30] = { 0 };
uint8_t Rx_Len = 0;
uint8_t Rx_Ok = 0;
bool RxDetect(void)
{
    bool ret = false;
    if (Rx_Ok == 1)
    {
        ret = Protocol_Hci_RecData(Rx_Buf, Rx_Len);
        if (ret == true)
        {
            Rx_Ok = 0;
        }
    }
    return ret;
}
/*******************************************************************/
void at5820_bsp_init(void) {
    bsp_io_init();
    bsp_usart_init();
    bsp_nvic_init();
    while(!RxDetect())
    {
        AT5820_Cmd_Set(HCI_DIST_SET, 1, 15);
        Protocol_Hci_FiFo_Poll();
        __delay_ms(200);
        AT5820_Cmd_Set(HCI_CFG_SAVE_SET, 1, 1);//val 1:save  0:no save 
        Protocol_Hci_FiFo_Poll();
        __delay_ms(300);
    }
}
